#include<cstdio>
#include<cctype>
#include<algorithm>
#define ls ch[x][0]
#define rs ch[x][1]
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std;

inline void rd(int &x){
    char ch; int t;
    for (t=0; !isdigit(ch=getchar()); t=(ch=='-'));
    for (x=ch-'0'; isdigit(ch=getchar()); x=x*10+ch-'0');
    if (t) x=-x;
}

const N=50100,M=100100,inf=1000000000;
int n,m,x,y,a,b,t,fa[N+M],tmp[N+M],ans=inf;
struct edge{ int x,y,a,b; }e[M];
bool operator <(edge a,edge b){ return a.a<b.a; }

int find(int x)
{ return fa[x]==x ? x : fa[x]=find(fa[x]);}

struct Tree{
    int val[M+N],mx[M+N],f[M+N],ch[M+N][2],rev[M+N];

    int isroot(int x)
    { return (!f[x])||(ch[f[x]][0]!=x && ch[f[x]][1]!=x);}
    void rev1(int x) {swap(ls,rs); rev[x]^=1;}
    void push(int x) { if (rev[x]) rev1(ls),rev1(rs),rev[x]=0;}
    void upd(int x){
        mx[x]=x;
        if (ls && val[mx[x]]<val[mx[ls]]) mx[x]=mx[ls];
        if (rs && val[mx[x]]<val[mx[rs]]) mx[x]=mx[rs];
    }

    void rot(int x){
        int y=f[x],z=f[y],w=ch[y][1]==x;
        ch[y][w]=ch[x][w^1]; f[ch[x][w^1]]=y;
        if (!isroot(y)) ch[z][ch[z][1]==y]=x;
        f[x]=z; f[y]=x; ch[x][w^1]=y; upd(y);
    }

    void splay(int x){
        int s=1,i=x; tmp[1]=x;
        while (!isroot(i)) tmp[++s]=i=f[i];
        while (s) push(tmp[s--]);
        while (!isroot(x)){
            int y=f[x];
            if (!isroot(y))
                ((ch[f[y]][1]==y)^(ch[y][1]==x)) ? rot(x) :rot(y);
            rot(x);
        }
        upd(x);
    }

    void access(int x){ for (int y=0; x; y=x,x=f[x]) splay(x),ch[x][1]=y,upd(x); }
    void mkroot(int x){ access(x); splay(x); rev1(x);}
    void link(int x,int y){ mkroot(x); f[x]=y; }
    void cut(int x,int y){ mkroot(x); access(y); splay(y); ch[y][0]=f[x]=0; upd(y); }
    int que(int x,int y){ mkroot(x); access(y); splay(y); return mx[y]; }
    int find(int x){ access(x); splay(x); while (ls) x=ls; return x; }

}T;

int main(){
    freopen("forest.in","r",stdin);
    freopen("forest.out","w",stdout);
    rd(n); rd(m); rep(i,1,n) fa[i]=i;
    rep(i,1,m) rd(e[i].x),rd(e[i].y),rd(e[i].a),rd(e[i].b);
    sort(e+1,e+m+1);
    rep(i,1,m){
        x=e[i].x; y=e[i].y; a=e[i].a; b=e[i].b;
        if (find(x)==find(y)){
            t=T.que(x,y);
            if (b<T.val[t]) T.cut(t,e[t-n].x),T.cut(t,e[t-n].y);
            else continue;
        }
        else fa[find(x)]=find(y);
        T.val[n+i]=b; T.mx[n+i]=n+i; T.link(x,n+i); T.link(y,n+i);
        if (find(1)==find(n)) ans=min(ans,T.val[T.que(1,n)]+a);
    }
    if (ans==inf) puts("-1"); else printf("%d\n",ans);
    return 0;
}